{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"http://hilpisch.com/tpq_logo.png\" alt=\"The Python Quants\" width=\"45%\" align=\"right\" border=\"4\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Framework Classes and Functions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This section explains the usage of some basic framework classes and functions of DX Analytics. Mainly some helper functions, the discounting classes and the market environment class used to store market data and other parameters/data needed to model, value and risk manage derivative instruments. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from dx import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "np.set_printoptions(precision=3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Helper Functions"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There are two helper functions used regulary:\n",
    "\n",
    "* <code>get_year_deltas</code>: get a list of year deltas (decimal fractions) relative to first value in time_list\n",
    "* <code>sn_random_numbers</code>: get an array of standard normally distributed pseudo-random numbers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### get_year_deltas"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Suppose we have a `list` object containing a number of `datetime` objects."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "time_list = [dt.datetime(2015, 1, 1),\n",
    "             dt.datetime(2015, 4, 1),\n",
    "             dt.datetime(2015, 6, 15),\n",
    "             dt.datetime(2015, 10, 21)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Passing this object to the `get_year_deltas` functions yields a list of year fractions representing the time intervals between the dates given. This is sometimes used e.g. for discounting purposes."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.   , 0.247, 0.452, 0.803])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "get_year_deltas(time_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### sn_random_numbers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Monte Carlo simulation of course relies heavily an the use of random numbers. The function `sn_random_numbers` is a wrapper function around the pseudo-random number generator of the `NumPy` library. It implements antithetic variates and moment matching as generic variance reduction techniques. It also allows to fix the seed value for the random number generator. The `shape` parameter is a `tuple` object of three integers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "ran = sn_random_numbers((2, 3, 4), antithetic=True,\n",
    "                        moment_matching=True, fixed_seed=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 0.067, -1.202, -0.067,  1.202],\n",
       "        [-0.245,  0.569,  0.245, -0.569],\n",
       "        [-1.659,  0.647,  1.659, -0.647]],\n",
       "\n",
       "       [[ 0.389, -1.974, -0.389,  1.974],\n",
       "        [ 0.424, -1.451, -0.424,  1.451],\n",
       "        [-0.79 ,  0.193,  0.79 , -0.193]]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ran"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using moment matching makes sure that the first and second moments match exactly 0 and 1, respectively."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ran.mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ran.std()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Setting the first value of the `shape` parameter to 1 yields a two-dimensional `ndarray` object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "ran = sn_random_numbers((1, 3, 4), antithetic=True,\n",
    "                        moment_matching=True, fixed_seed=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.963,  0.494,  0.963, -0.494],\n",
       "       [ 0.033,  1.412, -0.033, -1.412],\n",
       "       [ 1.542, -0.676, -1.542,  0.676]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ran"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Discounting Classes"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the risk-neutral valuation of derivative instrumente, discounting payoffs is a major task. The following discounting classes are implemented:\n",
    "\n",
    "* `constant_short_rate`: fixed short rate\n",
    "* `deterministic_yield`: deterministic yiels/term structure"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### constant_short_rate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `constant_short_rate` class represents the most simple case for risk-neutral discounting. A discounting object is defined by instatiating the class and providing a name and a decimal short rate value only."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "r = constant_short_rate('r', 0.05)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'r'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.05"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.short_rate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The object has a method `get_forward_rates` to generate forward rates given, for instance, a `list` object of `datetime` objects."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([datetime.datetime(2015, 1, 1, 0, 0),\n",
       "  datetime.datetime(2015, 4, 1, 0, 0),\n",
       "  datetime.datetime(2015, 6, 15, 0, 0),\n",
       "  datetime.datetime(2015, 10, 21, 0, 0)],\n",
       " array([0.05, 0.05, 0.05, 0.05]))"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.get_forward_rates(time_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similarly, the method `get_discount_factors` returns discount factors for such a `list` object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([datetime.datetime(2015, 1, 1, 0, 0),\n",
       "  datetime.datetime(2015, 4, 1, 0, 0),\n",
       "  datetime.datetime(2015, 6, 15, 0, 0),\n",
       "  datetime.datetime(2015, 10, 21, 0, 0)],\n",
       " array([0.961, 0.978, 0.988, 1.   ]))"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.get_discount_factors(time_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also pass, for instance, an `ndarry` object containing year fractions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0. , 1. , 1.5, 2. ]), array([0.905, 0.928, 0.951, 1.   ]))"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.get_discount_factors(np.array([0., 1., 1.5, 2.]),\n",
    "                       dtobjects=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### deterministic_short_rate"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `deterministic_short_rate` class allows to model an interest rate term structure. To this end, you need to pass a `list` object of `datetime` and yield pairs to the  class."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "yields = [(dt.datetime(2015, 1, 1), 0.02),\n",
    "          (dt.datetime(2015, 3, 1), 0.03),\n",
    "          (dt.datetime(2015, 10, 15), 0.035),\n",
    "          (dt.datetime(2015, 12, 31), 0.04)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "y = deterministic_short_rate('y', yields)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'y'"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[datetime.datetime(2015, 1, 1, 0, 0), 0.02],\n",
       "       [datetime.datetime(2015, 3, 1, 0, 0), 0.03],\n",
       "       [datetime.datetime(2015, 10, 15, 0, 0), 0.035],\n",
       "       [datetime.datetime(2015, 12, 31, 0, 0), 0.04]], dtype=object)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.yield_list"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The method `get_interpolated_yields` implements an interpolation of the yield data and returns the interpolated yields given a `list` object of `datetime` objects."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[datetime.datetime(2015, 1, 1, 0, 0), 0.019999999999999993,\n",
       "        0.0840608597791612],\n",
       "       [datetime.datetime(2015, 4, 1, 0, 0), 0.03283048934520345,\n",
       "        0.02532998361805569],\n",
       "       [datetime.datetime(2015, 6, 15, 0, 0), 0.035133049718591186,\n",
       "        0.0007769642303797064],\n",
       "       [datetime.datetime(2015, 10, 21, 0, 0), 0.03515012570984609,\n",
       "        0.010083939037494674]], dtype=object)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.get_interpolated_yields(time_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In similar fashion, the methods `get_forward_rates` and `get_discount_factors` return forward rates and discount factors, respcectively."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([datetime.datetime(2015, 1, 1, 0, 0),\n",
       "  datetime.datetime(2015, 4, 1, 0, 0),\n",
       "  datetime.datetime(2015, 6, 15, 0, 0),\n",
       "  datetime.datetime(2015, 10, 21, 0, 0)],\n",
       " array([0.019999999999999993, 0.039076238730477456, 0.0354842801241053,\n",
       "        0.04324490417008154], dtype=object))"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.get_forward_rates(time_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([datetime.datetime(2015, 1, 1, 0, 0),\n",
       "  datetime.datetime(2015, 4, 1, 0, 0),\n",
       "  datetime.datetime(2015, 6, 15, 0, 0),\n",
       "  datetime.datetime(2015, 10, 21, 0, 0)],\n",
       " [0.9716610313922761, 0.9787638348236196, 0.9862902768276359, 1.0])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y.get_discount_factors(time_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Market Environment"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `market_environment` class is used to collect relevant data for the modeling, valuation and risk management of single derivatives instruments and portfolios composed of such instruments. A `market_environment` object stores:\n",
    "\n",
    "* `constants`: e.g. maturity date of option\n",
    "* `lists`: e.g. list of dates\n",
    "* `curves`: e.g. discounting objects\n",
    "\n",
    "A `market_environment` object is instantiated by providing a name as a `string` object and the pricing date as a `datetime` object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "me = market_environment(name='me', pricing_date=dt.datetime(2014, 1, 1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Constants are added via the `add_constant` method and providing a key and the value."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "me.add_constant('initial_value', 100.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "me.add_constant('volatility', 0.25)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Lists of data are added via the  `add_list` method."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "me.add_list('dates', time_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `add_curve` method does the same for curves."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [],
   "source": [
    "me.add_curve('discount_curve_1', r)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "me.add_curve('discount_curve_2', y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The single data objects are stored in separate `dictionary` objects."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'initial_value': 100.0, 'volatility': 0.25}"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "me.constants"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'dates': [datetime.datetime(2015, 1, 1, 0, 0),\n",
       "  datetime.datetime(2015, 4, 1, 0, 0),\n",
       "  datetime.datetime(2015, 6, 15, 0, 0),\n",
       "  datetime.datetime(2015, 10, 21, 0, 0)]}"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "me.lists"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'discount_curve_1': <dx.frame.constant_short_rate at 0x10e05e208>,\n",
       " 'discount_curve_2': <dx.frame.deterministic_short_rate at 0x10e05e710>}"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "me.curves"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Data is retrieved from a `market_environment` object via the `get_constant`, `get_list` and `get_curve` methods and providing the respective key."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.25"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "me.get_constant('volatility')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[datetime.datetime(2015, 1, 1, 0, 0),\n",
       " datetime.datetime(2015, 4, 1, 0, 0),\n",
       " datetime.datetime(2015, 6, 15, 0, 0),\n",
       " datetime.datetime(2015, 10, 21, 0, 0)]"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "me.get_list('dates')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<dx.frame.constant_short_rate at 0x10e05e208>"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "me.get_curve('discount_curve_1')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Retrieving, for instance, a discounting object you can in one step retrieve it and call a method on it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "([datetime.datetime(2015, 1, 1, 0, 0),\n",
       "  datetime.datetime(2015, 4, 1, 0, 0),\n",
       "  datetime.datetime(2015, 6, 15, 0, 0),\n",
       "  datetime.datetime(2015, 10, 21, 0, 0)],\n",
       " [0.9716610313922761, 0.9787638348236196, 0.9862902768276359, 1.0])"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "me.get_curve('discount_curve_2').get_discount_factors(time_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Copyright, License & Disclaimer**\n",
    "\n",
    "© Dr. Yves J. Hilpisch | The Python Quants GmbH\n",
    "\n",
    "DX Analytics (the \"dx library\" or \"dx package\") is licensed under the GNU Affero General\n",
    "Public License version 3 or later (see http://www.gnu.org/licenses/).\n",
    "\n",
    "DX Analytics comes with no representations or warranties, to the extent\n",
    "permitted by applicable law.\n",
    "\n",
    "http://tpq.io | [dx@tpq.io](mailto:team@tpq.io) |\n",
    "http://twitter.com/dyjh\n",
    "\n",
    "<img src=\"http://hilpisch.com/tpq_logo.png\" alt=\"The Python Quants\" width=\"35%\" align=\"right\" border=\"0\"><br>\n",
    "\n",
    "**Quant Platform** | http://pqp.io\n",
    "\n",
    "**Python for Finance Training** | http://training.tpq.io\n",
    "\n",
    "**Certificate in Computational Finance** | http://compfinance.tpq.io\n",
    "\n",
    "**Derivatives Analytics with Python (Wiley Finance)** |\n",
    "http://dawp.tpq.io\n",
    "\n",
    "**Python for Finance (2nd ed., O'Reilly)** |\n",
    "http://py4fi.tpq.io"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
